/**
 * ----------------------------------------------------------
 * 
 * Demo Page for BIMRUN Viewer V3.7
 * 
 * 
 * @Date 2020.05
 * 
 * @Developer Yuan Yao, Mao Weiqing @SUIT
 * 
 * 
 * 
 * ----------------------------------------------------------
 */

// 2020-07-04 yaoyuan: test iOS system
let isIOS = /(iPhone|iPad|iPod|iOS)/i.test( navigator.userAgent );

let isMacOS = /(Mac OS)/i.test( navigator.userAgent);

if( isMacOS && navigator.maxTouchPoints === 5) isIOS = true; //适配最新版的ipad os和mac os代理相同的问题


let container = document.getElementById( "container" );


let viewer = new Viewer( {

    container: container,
    indicator: { url: "./resources/aim.png", size: 50 },

} );

let sceneId = '288242761'; //小房子场景

let projectId = '288242760'; //城市综合体项目

viewer.createNavCube( viewer.container );


viewer.setCameraPosition( 100000, 100000, 100000 );
viewer.setCameraLookat( 0, 0, 0 );


// 模型加载
if ( getUrlParams( "sceneId" ) ) {

    // 根据场景id加载场景
    viewer.loadScene( getUrlParams( "sceneId" ) );

} else if ( getUrlParams( "projectId" ) ) {

    // 根据项目id加载项目
    viewer.loadProject( getUrlParams( "projectId" ) );

} else {

    viewer.loadScene( sceneId );

}



/**
 * 
 * buttons
 * 
 */
// 2020-06-11 yaoyuan: 加载场景
let loadSceneBtn = document.getElementById( "loadScene" );
loadSceneBtn.addEventListener( 'click', () => {
    viewer.loadScene( sceneId );
} );

// 2020-06-11 yaoyuan: 隐藏场景
document.getElementById( "hideScene" ).addEventListener( 'click', () => {
    viewer.hideScene( sceneId );
} );

// 2020-06-11 yaoyuan: 显示场景
document.getElementById( "displayScene" ).addEventListener( 'click', () => {
    viewer.disPlayScene( sceneId );
} );

// 2020-06-15 mwq: 加载项目
let loadProjectBtn = document.getElementById( 'loadProject' );
loadProjectBtn.addEventListener( 'click', () => {

    viewer.loadProject( projectId );
} );
// 2020-06-15 mwq: 隐藏项目
let hideProjectBtn = document.getElementById( 'hideProject' );
hideProjectBtn.addEventListener( 'click', () => {

    viewer.hideProject( projectId );
} );

// 2020-06-15 mwq: 显示项目
let displayProjectBtn = document.getElementById( 'displayProject' );
displayProjectBtn.addEventListener( 'click', () => {

    viewer.displayProject( projectId );
} );

// 2020-06-11 yaoyuan: 视角包围盒
// document.getElementById( "camToSceneBox" ).addEventListener( 'click', () => {
//     loadDoneCB();
// } );

// 2020-06-11 yaoyuan: 剖面相关
let clipPlanes = [];
// 2020-06-11 yaoyuan: 添加剖面
document.getElementById( "addClippingPlane" ).addEventListener( 'click', () => {
    let plane = viewer.addClippingPlane( { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 }, 100, 100, Math.round( Math.random() * 16777215 ), 0.2 );
    clipPlanes.push( plane );

    plane = viewer.addClippingPlane( { x: 0, y: 0, z: 0 }, { x: 0, y: 1, z: 0 }, 100, 100, Math.round( Math.random() * 16777215 ), 0.2 );
    clipPlanes.push( plane );

    // let plane = viewer.addClippingPlane( { x: 18370.259520710275, y: 62559.76510425813, z: 768.3489999999999 }, { x: 0, y: 0, z: -1 }, 1000, 1000 );
    // clipPlanes.push( plane );
    // plane = viewer.addClippingPlane( { x: 18370.259520710275, y: 62559.76510425813, z: 761.658 }, { x: 0, y: 0, z: 1 }, 1000, 1000 );
    // clipPlanes.push( plane );
} );

// 2020-06-11 yaoyuan: 添加剖面盒
document.getElementById( "addClippingBox" ).addEventListener( 'click', () => {
    let planes = viewer.addClippingBox( { x: 0, y: 0, z: 0 }, 200, 200, 200 );
    clipPlanes = clipPlanes.concat( planes );
} );

// 2020-06-11 yaoyuan: 删除单个剖面
document.getElementById( "delClippingPlane" ).addEventListener( 'click', () => {
    clipPlanes.pop().deleteClippingPlane();
} );

// 2020-06-11 yaoyuan: 删除所有剖面
document.getElementById( "delAllClippingPlane" ).addEventListener( 'click', () => {
    viewer.deleteAllClippingPlanes();
} );

// 2020-11-30 mwq: 隐藏所有剖面
let clippingPlaneVisibility = true;
document.getElementById( "displayAllClippingPlane" ).addEventListener( 'click', () => {
    clippingPlaneVisibility = !clippingPlaneVisibility;
    viewer.displayAllClippingPlanes( clippingPlaneVisibility );
} );

// 2020-06-11 yaoyuan: 开启和退出测量模式
document.getElementById( "measureDistance" ).addEventListener( 'click', function ( e ) {
    if ( e.currentTarget.checked ) {
        viewer.enterMeasureMode( 0.01, 0xf95628, 0xf95628, 'white', 2, "m" );
    } else {
        viewer.leaveMeasureMode();
    }
} );

// 2020-08-03 yaoyuan: 框选模式
document.getElementById( "dragSelection" ).addEventListener( 'click', function ( e ) {
    viewer.enableDragSelection( e.currentTarget.checked );
} );

// 2020-08-03 yaoyuan: 顶点边线吸附模式
document.getElementById( "snapping" ).addEventListener( 'click', function ( e ) {
    viewer.enableSnapping( e.currentTarget.checked );
} );

// 2020-06-12 yaoyuan: 添加点精灵
let sprite = null;
let spriteContainer = viewer.addSpritesSubContainer();
// let spriteContainer = null;
var spriteListenerFn = (e)=>{
    console.log(e);
}
document.getElementById( "addSprite" ).addEventListener( 'click', () => {
    let content = document.createElement( 'div' );
    content.innerHTML = 'hello';
    let postion = { x: -5.858663244869632, y: -25.9845984306274, z: -2.189296511781116 };
    let onMaterialLoaded = function () {
        console.log( 'onMaterialLoaded in spritePlugin' );  // 2020-07-13 mwq changed:增加了onMaterialLoaded回调函数
    }
    // spriteContainer = viewer.addSpritesSubContainer();
    sprite = spriteContainer.addSprite( postion, "./resources/bimrun.png", 0.1, content, onMaterialLoaded );
    // sprite.setTargetRadius(40);
    spriteContainer.setSpriteTargetRadius( sprite, 80 );

    viewer.addEventListener( BIMRUN.Events.SpriteClick, spriteListenerFn ) // 2020-10-09 mwq changed:将事件触发函数封装
    viewer.addEventListener( BIMRUN.Events.SpriteLeave, spriteListenerFn );
    viewer.addEventListener( BIMRUN.Events.SpriteEnter, spriteListenerFn );
} );

// 2021-3-29 MWQ: 添加点精灵闪烁的代码示例
var blinkingInterval = null; //Interval pointer

document.getElementById( "startSpriteBlinking" ).addEventListener( 'click', () => {

        let n = 0;

        if( sprite ){

            if( blinkingInterval ) { //如果有计时器，先清除计时器
                clearInterval(blinkingInterval);
            }

            blinkingInterval = setInterval(value => {
                n++;
                viewer.render();
                
                  if (n % 2) {
                    sprite.material.color = new THREE.Color(0xff0000); // 0xff0000;
                  } else {
                    sprite.material.color = new THREE.Color(0x00ff00);
                  }

              }, 200);
        }
} );

document.getElementById( "stopSpriteBlinking" ).addEventListener( 'click', () => {

    if( blinkingInterval ) {
        clearInterval(blinkingInterval);
    }

} );

document.getElementById( "showSprite" ).addEventListener( 'click', () => {

    spriteContainer.show();

} );

document.getElementById( "hideSprite" ).addEventListener( 'click', () => {

    spriteContainer.hide();  //我们不希望在开启剖面的情况下隐藏标签（点精灵）

} );

// 2020-06-12 yaoyuan: 移动点精灵
document.getElementById( "moveSprite" ).addEventListener( 'click', () => {

    spriteContainer.setSpritePosition( sprite, { x: 10, y: 10, z: 10 } );

} );

// 2020-06-12 yaoyuan: 删除点精灵
document.getElementById( "removeSprite" ).addEventListener( "click", function () {
    // spriteContainer.deleteSprites( [ sprite ] );
    spriteContainer.deleteAllSprites();
    // viewer.removeEventListener( BIMRUN.Events.SpriteClick, spriteListenerFn ); //建议注意主动维护事件的监听
    // viewer.removeEventListener( BIMRUN.Events.SpriteLeave, spriteListenerFn );
    // viewer.removeEventListener( BIMRUN.Events.SpriteEnter, spriteListenerFn );

} );

// 2020-06-16 yaoyuan: getCameraInfo
let camInfo = {
    position: { x: 16.634252930726994, y: 8.113031539441101, z: -1.3852625042204454 },
    quaternion: { x: 0.5402676162520264, y: -0.40261258939426703, z: -0.4415379275035211, w: 0.5925016998005085 },
    target: { x: 17.588447505035745, y: 8.397713044778149, z: -1.4772905156016385 }
}
document.getElementById( "getCameraInfo" ).addEventListener( "click", function () {
    camInfo = viewer.getCameraInfo();
    console.log( "CameraInfo", camInfo );
    alert( "Captured CameraInfo:\n" + JSON.stringify(camInfo) );
} );

// 2020-06-16 yaoyuan: flyToPoint
document.getElementById( "flyToPoint" ).addEventListener( "click", function () {
    
    if ( camInfo ) {
        alert( "fly to a point with fixed camera direction:\n" + JSON.stringify(camInfo.position) );
        viewer.flyToPoint( camInfo.position, 2000 ); 
    } else {
        alert( "fly to a point with fixed camera direction:\n" + JSON.stringify({ x: 20, y: 2, z: 2 }) );
        viewer.flyToPoint( { x: 20, y: 2, z: 2 }, 2000 );
    }
} );

// 2020-06-16 yaoyuan: flyTo
document.getElementById( "flyTo" ).addEventListener( "click", function () {
    alert( "fly to a point with custom camera view or direction:\n" + JSON.stringify(camInfo) );
    camInfo && viewer.flyTo( camInfo ); //移动相机到指定的视角方向位置
} );

// 2020-06-16 yaoyuan: flyToModel
document.getElementById( "flyToModel" ).addEventListener( "click", function () {
    let selected = viewer.getSelectedModels();
    if ( selected.length > 0 ) {
        viewer.flyToModel( selected[ 0 ] );
    } else {
        // console.log( "No selected models. " )
        alert( "No selected models. " );
    }
} );

// 2020-06-16 yaoyuan: adjustCameraBySceneIds
document.getElementById( "flyToScene" ).addEventListener( "click", function () {
    if ( sceneId ) viewer.adjustCameraBySceneIds( [ sceneId ] );
} );

// 2020-06-17 yaoyuan: 
let autoRotate = false;
document.getElementById( "switchRotateAround" ).addEventListener( "click", function () {
    autoRotate = !autoRotate;
    viewer.switchRotateAround( autoRotate );
} );

//2020-06-16 mwq: createAnimation
document.getElementById( "createAnimation" ).addEventListener( 'click', () => {
    var PathPoint = viewer.walkThrough.PathPoint;  //viewer.walkThroughPathPoint();
    var interPoints = [
        new PathPoint( { x: -60.86156955101433, y: -14.808798596107408, z: 31.46131999408458 }, { x: -0.4629240749351311, y: -14.808798596107408, z: 1.2619972560449817 }, 1000 ),
        new PathPoint( { x: 0.295077492368393, y: -81.83295609564193, z: 9.458547902914166 }, { x: -0.4629240749351311, y: -14.808798596107408, z: 1.2619972560449817 }, 1000 ),
        new PathPoint( { x: 48.18802440907026, y: -54.60759842953914, z: 10.314346927725694 }, { x: 4.4294962494080465, y: -14.134860402246403, z: -2.0691062270340237 }, 1000 ),
        new PathPoint( { x: 48.18914750119575, y: 16.63525372549021, z: 27.2822034942864 }, { x: -1.4283017426614268, y: -17.829765735879086, z: -2.888416811262081 }, 1000 ),
        new PathPoint( { x: -1.681234748364031, y: 48.3130680787334, z: 19.77645347324923 }, { x: -14.361718974093739, y: -11.180547532051783, z: -9.544386431665684 }, 1000 ),
    ];
    viewer.walkThrough.createPath( interPoints );
} );

//2020-06-16 mwq: createAnimation
document.getElementById( "startAnimation" ).addEventListener( 'click', () => {
    viewer.walkThrough.start();
} );

//2020-06-16 mwq: stopAnimation
document.getElementById( "stopAnimation" ).addEventListener( 'click', () => {
    // viewer.walkThrough.stop();//在老版本Tweenjs中stop当做暂停来使用，但并没有保存暂停时的信息（如时间等）
    viewer.walkThrough.stop(); //在新版本TweenJS中提供了pause方法，所以这里stop方法在内部调用的还是TweenJs的pause方法
} );

//2020-06-16 mwq: repeatAnimation
document.getElementById( "repeatAnimation" ).addEventListener( 'click', () => {
    viewer.walkThrough.repeat();
} );

//2020-06-17 mwq: testAnimation
document.getElementById( "testAnimation" ).addEventListener( 'click', () => {

    var PathPoint = viewer.walkThrough.PathPoint;  //注意PathPoint是一个对象，是对view.walkThrough.PathPoint的引用

    var interPoints = [
        new PathPoint( { x: -60.86156955101433, y: -14.808798596107408, z: 31.46131999408458 }, { x: -0.4629240749351311, y: -14.808798596107408, z: 1.2619972560449817 }, 1000 ),
        new PathPoint( { x: 0.295077492368393, y: -81.83295609564193, z: 9.458547902914166 }, { x: -0.4629240749351311, y: -14.808798596107408, z: 1.2619972560449817 }, 1000 ),
        new PathPoint( { x: 48.18802440907026, y: -54.60759842953914, z: 10.314346927725694 }, { x: 4.4294962494080465, y: -14.134860402246403, z: -2.0691062270340237 }, 1000 ),
        new PathPoint( { x: 48.18914750119575, y: 16.63525372549021, z: 27.2822034942864 }, { x: -1.4283017426614268, y: -17.829765735879086, z: -2.888416811262081 }, 1000 ),
        new PathPoint( { x: -1.681234748364031, y: 48.3130680787334, z: 19.77645347324923 }, { x: -14.361718974093739, y: -11.180547532051783, z: -9.544386431665684 }, 1000 ),
    ];

    viewer.walkThrough.createPath( interPoints );

    let step = 1; // step的单位是米， 表示相邻两个路径点之间的距离（length) 按照 step来划分，划分次数 = length / step |  结论：step越小，划分次数越多，动画越顺畅 

    //prepareView 方法是用来处理动画卡顿问题 interPoints 是前面构造的路径点， step是划分步长， viewer.walkThrough.start是回调函数，表示开始执行动画
    viewer.walkThrough.prepareView( interPoints, step, viewer.walkThrough.start ); //进入预加载路线


    // viewer.walkThrough.repeat();
} );

//元素渲染
let dom;
document.getElementById( "addDom" ).addEventListener( 'click', () => {
    dom = document.createElement( 'div' );
    dom.textContent = 'lookat here';
    viewer.addDom( dom, { x: 0, y: 0, z: 0 }, true );
} );

document.getElementById( "deleteDom" ).addEventListener( 'click', () => {
    viewer.deleteDom( dom );
} );

document.getElementById( "updateDomPosition" ).addEventListener( 'click', () => {
    viewer.updateDomPosition( dom, { x: 10, y: 10, z: 10 } );
} );

// 2020-06-19 yaoyuan: Particle System
let particleEffectFire, particleEffectStar;
let particleEffects = [];
document.getElementById( "addParticleEffect" ).addEventListener( 'click', () => {

    let particles = [];

    // Particles - fire
    for ( let i = 0; i < 2000; i++ ) {

        let location = new THREE.Vector3( 0.1 * Math.random(), 0, 0 );
        location.applyAxisAngle( new THREE.Vector3( 0, 0, 1 ), i / ( 2 * Math.PI ) );
        let xdir = location.x > 0 ? 1 : -1;
        let ydir = location.y > 0 ? 1 : -1;
        let zdir = location.z > 0 ? 1 : -1;

        let p = new BIMRUN.ParticleSystem.Particle( {

            location: location,

            velocity: new THREE.Vector3( 0, 0, -0.2 * Math.random() ),

            acceleration: new THREE.Vector3(
                -xdir * Math.random() * 0.1,
                -ydir * Math.random() * 0.1,
                Math.random() * 1.5 ),

            rotation: 0.0,

            size: 0 | ( Math.random() * 10 ),

            color: new THREE.Color( 0.8 + 0.2 * Math.random(), 0.1 + 0.2 * Math.random(), 0.1 + 0.2 * Math.random() ),

            start: 0 | ( Math.random() * 2000 ),

            life: 0 | ( 800 + Math.random() * 500 ),

            repeat: 0 | ( 800 + Math.random() * 500 ),

            fade: true

        } );

        particles.push( p );
    }

    particleEffectFire = new BIMRUN.ParticleSystem.ParticleEffect( particles, {
        texture: "./resources/spark.png"
    } );
    let pePosition = { x: Math.random() * 5, y: Math.random() * 5, z: 0.1 };
    particleEffectFire.setPosition( pePosition );


    // particles - star
    particles.length = 0;
    for ( let i = 0; i < 500; i++ ) {

        let location = new THREE.Vector3( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 );
        let xdir = Math.random() > 0.5 ? 1 : -1;
        let ydir = Math.random() > 0.5 ? 1 : -1;
        let zdir = Math.random() > 0.5 ? 1 : -1;

        let p = new BIMRUN.ParticleSystem.Particle( {

            location: location,

            velocity: new THREE.Vector3(
                xdir * Math.random() * 5,
                zdir * Math.random() * 5,
                15 + Math.random() * 15 ),

            acceleration: new THREE.Vector3( 0, 0, -9.8 ),

            rotation: 5,

            size: 0 | ( Math.random() * 50 ),

            color: new THREE.Color( Math.random(), Math.random(), Math.random() ),

            start: Math.random() * 5 * 1000,

            life: 0 | ( 5 * 1000 + Math.random() * 5 * 1000 ),

            repeat: 0 | ( 2 * 1000 + Math.random() * 2 * 1000 ),

            fade: true

        } );

        particles.push( p );
    }

    particleEffectStar = new BIMRUN.ParticleSystem.ParticleEffect( particles, {
        texture: "./resources/star.png"
    } );
    particleEffectStar.setPosition( { x: 0, y: 0, z: 0 } );

    particleEffects.push( particleEffectFire );
    particleEffects.push( particleEffectStar );

    viewer.addParticleEffects( particleEffects );

    viewer.flyToPoint( pePosition, 2000, 0.1 );

} );

//截图功能测试 mwq:2020-06-19 添加将图片下载功能
let convertBase64UrlToBlog = function ( base64 ) {
    let parts = base64.split( ";base64," );
    let contentType = parts[ 0 ].split( ":" )[ 1 ];
    let raw = window.atob( parts[ 1 ] );
    let rawLength = raw.length;
    let uInt8Array = new Uint8Array( rawLength );
    for ( let i = 0; i < rawLength; i++ ) {
        uInt8Array[ i ] = raw.charCodeAt( i );
    }
    return new Blob( [ uInt8Array ], { type: contentType } );
}

document.getElementById( "getScreenShot" ).addEventListener( 'click', () => {
    // var img = document.createElement('img');
    // img.src = viewer.getScreenshot(500* viewer.canvas.clientWidth / viewer.canvas.clientHeight, 500);
    // document.body.appendChild(img);

    let blob = convertBase64UrlToBlog( viewer.getScreenshot( 500 * viewer.canvas.clientWidth / viewer.canvas.clientHeight, 500 ) );
    let a = document.createElement( 'a' );
    a.style.display = 'none';
    a.download = 'filename.png';
    a.href = window.URL.createObjectURL( blob );
    a.click();
} );

//环境光亮度测试
let intensity = 0.6;
document.getElementById( "btnAddLuminosity" ).addEventListener( 'click', () => {
    intensity += 0.1;
    viewer.setLuminosity( intensity );
} );

document.getElementById( "btnMinusLuminosity" ).addEventListener( 'click', () => {
    intensity -= 0.1;
    viewer.setLuminosity( intensity );
} );

let backgroundToken = 0;
document.getElementById( 'btnSetBackground' ).addEventListener( 'click', () => {

    if ( backgroundToken === 0 ) {

        viewer.setSceneBackGroundColor( 0x121223 );
        backgroundToken = 1;

    } else if ( backgroundToken === 1 ) {

        viewer.setSceneBackGroundTexture( "./resources/bimrun.png" );
        backgroundToken = 0;

    }

} );

// 2020-07-13 yaoyuan: 热力图功能
let heatmap;
document.getElementById( 'btnCreateHeatmap' ).addEventListener( 'click', () => {

    let points = [];
    let max = 20;
    for ( let i = 0; i < 25; i++ ) {
        points.push( {
            x: Math.random(),
            y: Math.random(),
            value: Math.floor( 8 + Math.random() * ( max - 8 ) )
        } );
    }

    let width = 30, height = 30;
    let center = { x: -0.5794588487253667, y: -32.5891446392621, z: -1.3688191750338596 };
    heatmap = viewer.createHeatmap( {
        center: center,
        width: width,
        length: height,
        widthSegs: width * 10,
        lengthSegs: height * 10,
        heightRatio: 2,
        radius: 30,
        resolutionX: 256,
        resolutionY: 256,
        max: max,
        data: points
    } );

    viewer.flyToPoint( center, 2000, 10 );

} );

document.getElementById( 'btnLiftHeatmap' ).addEventListener( 'click', () => {

    if ( heatmap ) {
        heatmap.updateHeightRatio( heatmap.heightRatio + 1 );
    }

} );

document.getElementById( 'btnLowerHeatmap' ).addEventListener( 'click', () => {

    if ( heatmap && heatmap.heightRatio > 0 ) {
        heatmap.updateHeightRatio( heatmap.heightRatio - 1 );
    }

} );

document.getElementById( 'btnMoveHeatmap' ).addEventListener( 'click', () => {

    if ( heatmap ) {
        let pos = heatmap.plane.position;
        heatmap.updatePosition( pos.x + 1, pos.y + 1, pos.z );
    }

} );

document.getElementById( 'btnDelHeatmap' ).addEventListener( 'click', () => {

    if ( heatmap ) {
        heatmap.delete();
    }

} );


// 2020-07-17 yaoyuan: 添加外部模型示例
let geo = new THREE.BoxGeometry( 10, 5, 5 );
let material = new THREE.MeshBasicMaterial( { color: 0xff00ff, wireframe: true } );
let mesh = new THREE.Mesh( geo, material );
mesh.position.set( 10.9214453175894, 4.9395314210443, 7.106775065013078 );
mesh.updateMatrixWorld( true );

document.getElementById( 'btnAddCustomObject' ).addEventListener( 'click', () => {

    viewer.addCustomObject( mesh );

} );

document.getElementById( 'btnRemoveCustomObject' ).addEventListener( 'click', () => {

    viewer.removeCustomObject( mesh );

} );

document.getElementById( 'btnChangeCustomObject' ).addEventListener( 'click', () => {

    let mixInfo = [
        {
            position: { x: 10.9214453175894, y: 4.9395314210443, z: 7.106775065013078 },
            // quaternion: { x: 0.5995424843247644, y: -0.3412228751036374, z: -0.3580973320697389, w: 0.6291915922517023 },
            angle: { x: 0, y: 0, z: 0 }
        },
        {
            position: { x: 9.905778312532, y: 4.77004960077306, z: 3.1109424198041182 },
            // quaternion: { x: 0.5995424843247644, y: -0.3412228751036374, z: -0.3580973320697389, w: 0.6291915922517023 },
            angle: { x: Math.PI, y: 0, z: 0 }
        },
        {
            position: { x: 7.9361927235244, y: 4.72927119540213, z: 2.375678486062278 },
            // quaternion: { x: 0.5995424843247644, y: -0.3412228751036374, z: -0.3580973320697389, w: 0.6291915922517023 },
            angle: { x: Math.PI * 2, y: 0, z: 0 }
        },
        {
            position: { x: 6.8173410034713, y: 4.3867025816358, z: 5.2085991734369 },
            // quaternion: { x: 0.6108255721384369, y: -0.2986094130326687, z: -0.3220571916007548, w: 0.6587895750604066 },
            angle: { x: Math.PI * 3, y: Math.PI * 0.5, z: 0 }
        },
        {

            position: { x: 6.4451373512542, y: 4.34070539394577, z: 4.372074351149129 },
            // quaternion: { x: 0.6108255721384369, y: -0.2986094130326687, z: -0.3220571916007548, w: 0.6587895750604066 },
            angle: { x: Math.PI * 4, y: 0, z: 0 }
        } ];

    let mixer = viewer.createCustomObjectAnimation( mesh, mixInfo, [ 0, 500, 2000, 5000, 5000 ] );

    let fn = () => { console.log( 'complete animation' ) };
    mixer.setOnCompleteCallback( fn );

    mixer.start();

} );

document.getElementById( 'btnAddCustomBasicLine' ).addEventListener( 'click', () => {

    let points = [];
    points.push( new THREE.Vector3( 0, 0, 0 ) );
    points.push( new THREE.Vector3( 100, 100, 100 ) );
    points.push( new THREE.Vector3( 100, 0, 0 ) );

    let color = 0xff00ff;

    let width = 5;

    let line = viewer.addCustomBasicLine( points, color, width );

} );

document.getElementById( 'btnAddCustomDashedLine' ).addEventListener( 'click', () => {

    let points = [];
    points.push( new THREE.Vector3( 10, 0, 0 ) );
    points.push( new THREE.Vector3( 0, 10, 0 ) );
    points.push( new THREE.Vector3( 0, 10, 20 ) );

    let color = 0xff0000;

    let width = 5;

    let scale = 1;

    let dashSize = 1;

    let gapSize = 0.5;

    viewer.addCustomDashedLine( points, color, width, scale, dashSize, gapSize );

} );


//gridlines
document.getElementById( 'btnLoadGridlineFont' ).addEventListener( 'click', () => {
    let url = './resources/helvetiker_regular.typeface.json';
    let promise = viewer.loadGridlineFont( url ); //注意：在callback返回success后，才应该去调用viewer.createSceneGridlines方法
    promise.then( ( data ) => {
        alert( data + ', now you can createSceneGrids' );
    } ).catch( ( error ) => { console.warn( error ) } );
} );


document.getElementById( 'btnCreateSceneGrids' ).addEventListener( 'click', () => {
    //测试sceneID  2957076   fake:2973007
    viewer.addEventListener( 'GridLineEnter', data => { console.log( data ) } );
    viewer.addEventListener( 'GridLineLeave', data => { console.log( data ) } );

    // var gridLine = viewer.gridsPlugin.createSceneGrids(2957076, [5331717]);//, 5331718, 5330560]); //5330560 not exsit, just for test
    // viewer.createSceneGridlines( sceneId, [ 5331717, 5331718, 5330560 ] ); //5330560 not exsit, just for test
    // viewer.createSceneGridlines( sceneId, [239670940]);//, 239670941, 239670942, 239670943]);// 239670943]);
    viewer.createSceneGridlines( sceneId, [ 239683235 ] ); //不重叠数据

    // viewer.createSceneGridlines( sceneId, [239675497]);//, 239670941, 239670942, 239670943]);// 239670943]);



} );


document.getElementById( 'btnCreateCustomSceneGrids' ).addEventListener( 'click', () => {
    //测试sceneID  2957076   fake:2973007
    viewer.addEventListener( 'GridLineEnter', data => { console.log( data ) } );
    viewer.addEventListener( 'GridLineLeave', data => { console.log( data ) } );

    let levels = JSON.parse( '[{"id":5331716,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T17:24:15","lastUpdateDate":"2020-07-23T17:24:15","userId":20539,"originalId":"458c0e49-01bb-11d5-9302-0000863f27ad-000002b6","elevation":2.7000000333692973,"name":"Ceiling","symbol":"M_Level Head - Circle","projectId":2928007},{"id":5331717,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T17:24:15","lastUpdateDate":"2020-07-23T17:24:15","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-00030015","elevation":6.00000007415381,"name":"Roof Line","symbol":"M_Level Head - Circle","projectId":2928007},{"id":5331718,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T17:24:15","lastUpdateDate":"2020-07-23T17:24:15","userId":20539,"originalId":"ad0aad84-b47a-45ab-9e4a-7bfad0caa3be-0003beaf","elevation":3.000000037076905,"name":"Level 2","symbol":"M_Level Head - Circle","projectId":2928007},{"id":5331719,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T17:24:15","lastUpdateDate":"2020-07-23T17:24:15","userId":20539,"originalId":"656284ae-d84a-4c5c-ae16-d638fa151c7e-0007cc92","elevation":-0.8000000098871745,"name":"Foundation","symbol":"M_Level Head - Circle","projectId":2928007},{"id":5331720,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T17:24:15","lastUpdateDate":"2020-07-23T17:24:15","userId":20539,"originalId":"079d150e-b61b-46bb-a991-2bbcfc2d317a-0007dcc6","elevation":-0.5500000067974326,"name":"Level 1 Living Rm.","symbol":"M_Level Head - Circle","projectId":2928007},{"id":5331842,"familyId":305,"sceneId":2957076,"familyTypeId":305,"createDate":"2020-07-23T19:09:39","lastUpdateDate":"2020-07-23T19:09:39","userId":20539,"originalId":"e3e052f9-0156-11d5-9301-0000863f27ad-00000137","elevation":0.0,"name":"Level 3","symbol":"M_Level Head - Circle","projectId":2928007}]' );
    let gridLines = JSON.parse( '[{"id":5331770,"familyId":341,"points":[-4.938068543591731,7.776597130117628,0.0,-4.9380685435917515,-4.435644149768376,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fa61","max":{"z":11.605807290702774,"y":7.776597130117628,"x":-4.938068543591731},"min":{"z":-0.30480000376701355,"y":-4.435644149768377,"x":-4.9380685435917515},"useTailPoint":true,"name":"1","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331771,"familyId":341,"points":[-1.9380685065148273,7.776597130117625,0.0,-1.9380685065148473,-4.435644149768382,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002faa7","max":{"z":11.605807290702774,"y":7.776597130117625,"x":-1.9380685065148269},"min":{"z":-0.3048000037670138,"y":-4.4356441497683825,"x":-1.938068506514847},"useTailPoint":true,"name":"2","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331772,"familyId":341,"points":[1.061931530562078,7.7765971301176195,0.0,1.061931530562058,-4.435644149768387,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fab5","max":{"z":11.605807290702774,"y":7.7765971301176195,"x":1.061931530562078},"min":{"z":-0.30480000376701355,"y":-4.435644149768387,"x":1.061931530562058},"useTailPoint":true,"name":"3","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331773,"familyId":341,"points":[4.061931567638984,7.776597130117613,0.0,4.061931567638964,-4.435644149768391,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fab7","max":{"z":11.605807290702774,"y":7.776597130117613,"x":4.061931567638984},"min":{"z":-0.30480000376701355,"y":-4.435644149768392,"x":4.061931567638964},"useTailPoint":true,"name":"4","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331774,"familyId":341,"points":[7.061931604715889,7.776597130117608,0.0,7.061931604715845,-19.313766639197215,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fab9","max":{"z":11.605807290702774,"y":7.776597130117608,"x":7.061931604715889},"min":{"z":-0.30480000376701355,"y":-19.313766639197215,"x":7.061931604715845},"useTailPoint":true,"name":"5","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331775,"familyId":341,"points":[10.061931641792789,7.776597130117603,0.0,10.061931641792743,-19.313766639197226,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fabb","max":{"z":11.605807290702774,"y":7.776597130117603,"x":10.061931641792789},"min":{"z":-0.30480000376701355,"y":-19.313766639197226,"x":10.061931641792745},"useTailPoint":true,"name":"6","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331776,"familyId":341,"points":[13.061931678869692,7.776597130117598,0.0,13.061931678869646,-19.31376663919723,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fabd","max":{"z":11.605807290702774,"y":7.776597130117598,"x":13.061931678869692},"min":{"z":-0.30480000376701355,"y":-19.31376663919723,"x":13.061931678869648},"useTailPoint":true,"name":"9","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331777,"familyId":341,"points":[-13.352900457277425,2.7984060560038264,0.0,14.42117803327956,2.798406056003737,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fb0a","max":{"z":11.274942532692934,"y":2.7984060560038264,"x":14.421178033279558},"min":{"z":-8.233211767613579,"y":2.798406056003737,"x":-13.352900457277425},"useTailPoint":true,"name":"A","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331778,"familyId":341,"points":[-13.352900457277434,-0.20159398107306636,0.0,14.421178033279554,-0.2015939810731559,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fb53","max":{"z":11.274942532692934,"y":-0.20159398107306636,"x":14.421178033279554},"min":{"z":8.002386168446085,"y":-0.20159398107315588,"x":-13.352900457277434},"useTailPoint":true,"name":"B","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331779,"familyId":341,"points":[-13.352900457277443,-3.2015940181499527,0.0,14.42117803327955,-3.201594018150042,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef57b02a-5e81-49e7-93bb-ae5f002d921c-0002fb5a","max":{"z":11.274942532692933,"y":-3.2015940181499527,"x":14.421178033279551},"min":{"z":-0.304800003767013,"y":-3.201594018150042,"x":-13.352900457277443},"useTailPoint":true,"name":"C","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331780,"familyId":341,"points":[14.421178033279533,-6.201594055227154,0.0,6.130450723627904,-6.201594055227127,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef4ad1cb-015c-4bb6-9030-e7bb82f1dd34-000648d8","max":{"z":11.274942532692934,"y":-6.201594055227126,"x":14.421178033279533},"min":{"z":-1.9950000246561432,"y":-6.201594055227154,"x":6.130450723627903},"useTailPoint":true,"name":"D","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331781,"familyId":341,"points":[14.421178033279528,-9.201594092304095,0.0,6.130450723627899,-9.201594092304068,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T18:24:23","lastUpdateDate":"2020-07-23T18:24:23","userId":20539,"originalId":"ef4ad1cb-015c-4bb6-9030-e7bb82f1dd34-0006496f","max":{"z":11.274942532692934,"y":-9.201594092304068,"x":14.421178033279528},"min":{"z":-1.9950000246561426,"y":-9.201594092304095,"x":6.130450723627899},"useTailPoint":true,"name":"E","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007},{"id":5331841,"familyId":341,"points":[14.421178033279515,-18.201594203534814,0.0,6.130450723627886,-18.201594203534786,0.0],"useHeadPoint":false,"sceneId":2957076,"lineType":null,"familyTypeId":341,"createDate":"2020-07-23T19:09:39","lastUpdateDate":"2020-07-23T19:09:39","userId":20539,"originalId":"ef4ad1cb-015c-4bb6-9030-e7bb82f1dd34-0006582f","max":{"z":11.274942532692934,"y":-18.201594203534786,"x":14.421178033279515},"min":{"z":-1.995000024656143,"y":-18.201594203534814,"x":6.130450723627885},"useTailPoint":true,"name":"G","type":"line","symbol":null,"color":[0,0,0,1],"projectId":2928007}]' );

    let userData = { levels: levels, gridLines: gridLines };
    // var gridLine = viewer.gridsPlugin.createCustomSceneGrids(2957076, [5331717], userData);//, 5331718, 5330560]); //5330560 not exsit, just for test
    viewer.createCustomSceneGridlines( sceneId, [ 5331717, 5331718 ], userData );//, 5331718, 5330560]); //5330560 not exsit, just for test

} );

document.getElementById( 'btnShowSceneGrids' ).addEventListener( 'click', () => {

    viewer.showSceneGridlines( sceneId, [ 239670942, 239670943 ] );

} );

document.getElementById( 'btnHideSceneGrids' ).addEventListener( 'click', () => {

    viewer.hideSceneGridlines( sceneId, [ 239670940, 239670941, 239670942, 239670943 ] );

} );

document.getElementById( 'btnRemoveSceneGrids' ).addEventListener( 'click', () => {

    viewer.removeSceneGridlines( sceneId, [ 5331717, 5331718 ] );

} );

document.getElementById( 'btnRemoveAllGrids' ).addEventListener( 'click', () => {

    viewer.removeAllGridlines();

} );

let lineEnable = true;
document.getElementById( 'btnSetLineSolide' ).addEventListener( 'click', () => {

    lineEnable = !lineEnable;
    viewer.setGridlineOnTop( sceneId, undefined, lineEnable );  //开启该场景Id下所有轴网透视效果
    // viewer.setGridlineOnTop( 2957076, [ 5331717 ], lineEnable ); //开启该场景Id下，某一层的轴网透视效果


} );

document.getElementById( 'btnMouseOnLine' ).addEventListener( 'click', () => {

    viewer.enableGridlineMouseHover( true );

} );

document.getElementById( 'btnMouseOffLine' ).addEventListener( 'click', () => {

    viewer.enableGridlineMouseHover( false );


} );

//地理围栏

let fence;
document.getElementById( 'btnAddFence' ).addEventListener( 'click', () => {

    var points = [
        { x: -15, y: 14 },
        { x: -27, y: -16 },
        { x: 10, y: -5 },
        { x: 40, y: -25 },
        { x: 30, y: 6 },
        { x: 40, y: 6 },
        { x: 50, y: 28 },
        { x: 6, y: 10 },
        { x: -15, y: 14 },

    ];
    let minZ = -4;
    let maxZ = 5;
    let colorHex = 0xff012ff;
    let opacity = 1;
    let parameters = {
        colorHex: colorHex,
        opacity: opacity,
        disableBottomPlane: false,
        disableTopPlane: true
    };
    fence = viewer.createFence( points, minZ, maxZ, parameters );
} );

let fenceEnable = true;
document.getElementById( 'btnSetFenceVisible' ).addEventListener( 'click', () => {
    if ( fence ) {
        fenceEnable = !fenceEnable;
        fence.setVisibility( fenceEnable );
    }
} );

document.getElementById( 'btnRemoveFence' ).addEventListener( 'click', () => {
    if ( fence ) {
        fence.remove();
    }
} );

document.getElementById( 'btnIsInFence' ).addEventListener( 'click', () => {
    if ( fence ) {

        let ans = viewer.isInFence( fence, { x: -15, y: 14, z: 5 } );
        console.log( ans );

    }
} );

//QRCode 二维码
document.getElementById( 'btnLoadQRCodeImage' ).addEventListener( 'click', () => {
    let imgSrc = './resources/QRCode.png';
    var callback = ()=>console.log('success');
    viewer.loadQRCodeImage(imgSrc, callback);
} );

let currentQRCode = null;
document.getElementById( 'btnAddQRCode' ).addEventListener( 'click', () => {
    //利用获取到的 position(位置),quaternion(旋转),normal(法向量)信息来放置二维码
    var position = new THREE.Vector3( -1.4480724840732964, 0.90308100726146, 3.9420178113486664); 
    var quaternion = new THREE.Quaternion(0.4999860422392401, -0.5000139573711326, -0.5000139573711327, 0.4999860422392399);
    var normal = new THREE.Vector3(-0.999999685542652, -0.000752237120979714, -0.00025110537741577843);

    currentQRCode = viewer.addQRCode(position, quaternion);

    let target = position, cameraPos = position.clone().add(normal); //从相机看向二维码，所以二维码的position为相机朝向的target
    
    viewer.flyToPositionTarget( cameraPos, target );

} );


document.getElementById( 'btnCreateQRCode' ).addEventListener( 'click', () => {
    //当创建二维码随着鼠标移动时，坐标左键将会放置二维码，并且触发事件 BIMRUN.Events.QRCodeChanged
    viewer.addEventListener(BIMRUN.Events.QRCodeChanged, (data)=>{
        console.log(data.position, data.quaternion, data.normal); //位置，旋转，法向量
        currentQRCode = data.object; //二维码模型
    });
    viewer.createQRCode(); //调用该函数会触发 QRCodeChanged 事件
} );


document.getElementById( 'btnRotateQRCode' ).addEventListener( 'click', () => {

    if(currentQRCode !== null){
        viewer.rotateQRCode(currentQRCode, 20); //角度
    }
    
} );

document.getElementById( 'btnTranslateQRCode' ).addEventListener( 'click', () => {
    if(currentQRCode !== null){
        viewer.translateQRCode(currentQRCode, 0.2 * Math.random(), 0.2 * Math.random()); //(obj,x,y) 向x正方向移动-1，向y轴移动1，单位 m  
    }
    
} );

var showQRCode = false;
document.getElementById( 'btnDisplayQRCode' ).addEventListener( 'click', () => {
    if(currentQRCode !== null){
        if(showQRCode){
            viewer.showQRCode(currentQRCode);

        }else{
            viewer.hideQRCode(currentQRCode);
        }
        showQRCode = !showQRCode;
    }
} );

//删除QRCode
document.getElementById( 'btnDeleteQRCode' ).addEventListener( 'click', () => {
    if(currentQRCode !== null){

        viewer.deleteQRCode(currentQRCode);
        currentQRCode = null;

    }
} );

//调整模型权重
document.getElementById( 'btnUpdateModelWeight' ).addEventListener( 'click', ()=>{
    var models = viewer.getSelectedModels();
    var weights = [];
    models.forEach(model=>{
        // weights.push(Math.random() * 10);
        weights.push(1024.0);
    })
    viewer.updateModelWeights(models, weights);
})

//对齐包围盒最大的模型权重
document.getElementById( 'btnUpdateModelWeightByAlignMaximumBox' ).addEventListener( 'click', ()=>{
    var models = viewer.getSelectedModels();
    var weights = [];
    let maxArea = -1.0, maxAreaIndex = -1; 
    let weightedProjectionArea; //带有权重的投影面积
    for(let i = 0, len = models.length; i<len; i++){
        let model = models[i];
        weightedProjectionArea = viewer.getExtentsProjectionArea(model.extents) * model.weight;
        if(weightedProjectionArea > maxArea){
            maxAreaIndex = i;
            maxArea = weightedProjectionArea;
        }
    }
    models.splice(maxAreaIndex, 1);  //其中投影面积最大的那个models不需要更新它的权重，所以从models数组中删除

    for(let i =0, len = models.length; i<len; i++){  //除去最大包围盒的model后的models数组

        let model = models[i];
        
        weightedProjectionArea = viewer.getExtentsProjectionArea(model.extents);

        weights.push(maxArea/weightedProjectionArea);  //构造对应的weight数组

    }
    viewer.updateModelWeights(models, weights);
})


/**
 * 
 * Private funcs
 * 
 */
function getUrlParams ( variable ) {

    let res = null;
    let query = window.location.search.substring( 1 );
    let vars = query.split( "&" );

    for ( let i = 0; i < vars.length; i++ ) {
        let pair = vars[ i ].split( "=" );
        if ( pair[ 0 ] == variable ) { res = pair[ 1 ]; }
    }

    if ( !isNaN( parseFloat( res ) ) ) res = parseFloat( res );
    else if ( !isNaN( parseInt( res ) ) ) res = parseInt( res );
    else if ( res === "true" ) res = true;
    else if ( res === "false" ) res = false;

    return res;

}